package com.hzw.saas.service.old.hub.service;

import java.io.File;
import java.util.List;

import com.hzw.saas.common.util.enums.ConflictModeEnum;
import com.hzw.saas.service.old.hub.pojo.FileStorage;
import com.hzw.saas.service.old.hub.pojo.InxChunkMetadata;
import com.hzw.saas.service.old.hub.pojo.InxChunkStorage;
import com.hzw.saas.service.old.hub.pojo.LocChunkStorage;
import cn.hutool.core.io.IORuntimeException;

/**
 * 分片存储接口
 * 路径参数均支持绝对路径和相对路径，相对路径的根路径为classpath
 *
 * @author zzl
 * @since 04/21/2021
 */
public interface IChunkStorageService {

    /**
     * 获取分片文件
     *
     * @param fileId     文件唯一标识(ID)
     * @param chunkId    分片ID/分片索引
     * @param superPaths 分片父路径
     * @return 目标分片文件
     */
    File getChunk(String fileId, String chunkId, String... superPaths);

    /**
     * 检查分片是否存在
     *
     * @param fileId     文件唯一标识(ID)
     * @param chunkId    分片ID/分片索引
     * @param superPaths 分片父路径
     * @return true 存在，false 不存在
     */
    boolean existsChunk(String fileId, String chunkId, String... superPaths);

    /**
     * 检查分片长度
     *
     * @param fileId     文件唯一标识(ID)
     * @param chunkId    分片ID/分片索引
     * @param superPaths 分片父路径
     * @return true 校验成功, false 校验失败或文件不存在
     */
    long getChunkLength(String fileId, String chunkId, String... superPaths);

    /**
     * 校验分片摘要，MD5
     *
     * @param digestType 摘要类型，支持md5,sha1,sha256。为空或其他则默认使用md5
     * @param fileId     文件唯一标识(ID)
     * @param chunkId    分片ID/分片索引
     * @param superPaths
     * @return true 校验成功, false 校验失败或文件不存在
     */
    String getChunkDigest(String digestType, String fileId, String chunkId, String... superPaths);


    /**
     * 保存分片数据，ID模式
     *
     * @param chunkInfo  分片信息
     * @param chunkBytes 分片数据
     */
    void saveChunk(LocChunkStorage chunkInfo, byte[] chunkBytes);

    /**
     * 保存分片数据，队列模式
     *
     * @param chunkInfo  分片信息
     * @param chunkBytes 分片数据
     */
    void saveChunk(InxChunkStorage chunkInfo, byte[] chunkBytes);

    /**
     * 删除分片
     *
     * @param fileId     文件唯一标识(ID)
     * @param chunkId    分片ID/分片索引
     * @param superPaths 分片父路径
     */
    void deleteChunk(String fileId, String chunkId, String... superPaths);

    /**
     * 删除文件的所有分片
     *
     * @param fileId     文件ID
     * @param superPaths 分片父路径
     */
    void deleteChunks(String fileId, String... superPaths);

    /**
     * 写入分片操作元数据
     * 请先调用读取分片数据获取已有的元数据信息，避免重要数据被覆盖
     *
     * @param inxChunkMetadata 分片操作元数据
     * @param fileId           文件ID
     * @param superPaths       分片父路径
     */
    void writeChunkMetadata(InxChunkMetadata inxChunkMetadata, String fileId, String... superPaths);

    /**
     * 读取分片操作元数据
     *
     * @param fileId     文件ID
     * @param superPaths 分片父路径
     * @return
     */
    InxChunkMetadata readChunkMetadata(String fileId, String... superPaths);

    /**
     * 合并文件分片
     *
     * @param fileInfo       目标文件信息
     * @param chunkSuperPath 分片目录路径
     * @param fileId         文件唯一标识(ID)
     * @param chunkInfoList  分片信息
     * @param delChunks      合并完成后是否删除分片
     * @param mode           同名冲突解决方式
     * @return 合并后的文件
     * @throws IORuntimeException check FileNotFoundException(分片不存在)
     */
    File mergeFileChunks(FileStorage fileInfo, String chunkSuperPath, String fileId, List<LocChunkStorage> chunkInfoList, boolean delChunks, ConflictModeEnum mode) throws IORuntimeException;

    /**
     * 追加文件分片
     *
     * @param fileInfo       目标文件信息
     * @param chunkSuperPath 分片目录路径
     * @param fileId         文件唯一标识(ID)
     * @param chunkInfoList  分片信息
     * @param delChunks      合并完成后是否删除分片
     * @param mode           同名冲突解决方式
     * @return 合并后的文件
     * @throws IORuntimeException check FileNotFoundException(分片不存在)
     */
    File appendFileChunks(FileStorage fileInfo, String chunkSuperPath, String fileId, List<LocChunkStorage> chunkInfoList, boolean delChunks, ConflictModeEnum mode) throws IORuntimeException;

    /**
     * @param fileInfo       目标文件信息
     * @param chunkSuperPath 分片父路径
     * @param fileId         文件唯一标识(ID)
     * @param delChunks      合并完成后是否删除分片
     * @param mode           同名冲突解决方式
     * @return 合并后的文件
     * @throws IORuntimeException check FileNotFoundException(分片不存在)
     */
    File mergeFileChunks(FileStorage fileInfo, String chunkSuperPath, String fileId, boolean delChunks, ConflictModeEnum mode) throws IORuntimeException;

}
